﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Security.Principal;
using System.Security.AccessControl;

namespace AMPLibrary.Windows
{
    public class FileSystemAccess
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static bool CheckReadAccess(string path)
        {
            WindowsIdentity windowsIdentity = WindowsIdentity.GetCurrent();
            DirectoryInfo directory = new DirectoryInfo(path);
            
            if (directory.Root.FullName == path)
                return true;

            // Get the collection of authorization rules that apply to the current directory
            AuthorizationRuleCollection authorizationRuleCollection = directory.GetAccessControl().GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier));

            // These are set to true if either the allow read or denyread access rights are set
            bool allowRead = false;
            bool denyRead = false;

            foreach (FileSystemAccessRule currentRule in authorizationRuleCollection)
            {
                // If the current rule applies to the current user
                if (windowsIdentity.User.Equals(currentRule.IdentityReference))
                {
                    if (currentRule.AccessControlType.Equals(AccessControlType.Deny))
                    {
                        if ((currentRule.FileSystemRights & FileSystemRights.Read) == FileSystemRights.Read)
                            denyRead = true;
                    }
                    else if (currentRule.AccessControlType.Equals(AccessControlType.Allow))
                    {
                        if ((currentRule.FileSystemRights & FileSystemRights.Read) == FileSystemRights.Read)
                            allowRead = true;
                    }
                }
            }

            if (allowRead & !denyRead)
                return true;
            else
                return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="user"></param>
        /// <param name="path"></param>
        /// <returns></returns>
        public static bool CheckReadAccess(WindowsIdentity user, string path)
        {
            DirectoryInfo directory = new DirectoryInfo(path);

            // Get the collection of authorization rules that apply to the current directory
            AuthorizationRuleCollection authorizationRuleCollection = directory.GetAccessControl().GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier));

            // These are set to true if either the allow read or denyread access rights are set
            bool allowRead = false;
            bool denyRead = false;

            foreach (FileSystemAccessRule currentRule in authorizationRuleCollection)
            {
                // If the current rule applies to the current user
                if (user.User.Equals(currentRule.IdentityReference))
                {
                    if (currentRule.AccessControlType.Equals(AccessControlType.Deny))
                    {
                        if ((currentRule.FileSystemRights & FileSystemRights.Read) == FileSystemRights.Read)
                            denyRead = true;
                    }
                    else if (currentRule.AccessControlType.Equals(AccessControlType.Allow))
                    {
                        if ((currentRule.FileSystemRights & FileSystemRights.Read) == FileSystemRights.Read)
                            allowRead = true;
                    }
                }
            }

            if (allowRead & !denyRead)
                return true;
            else
                return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static bool IsRestricted(string path)
        {
            if (Environment.GetFolderPath(Environment.SpecialFolder.Windows).ToLower() == path.ToLower())
                return true;

            if (Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles).ToLower() == path.ToLower())
                return true;

            if (Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86).ToLower() == path.ToLower())
                return true;

            if (Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFilesX86).ToLower() == path.ToLower())
                return true;
            
            if (Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFiles).ToLower() == path.ToLower())
                return true;

            if (Environment.GetFolderPath(Environment.SpecialFolder.NetworkShortcuts).ToLower() == path.ToLower())
                return true;

            if (Environment.GetFolderPath(Environment.SpecialFolder.Templates).ToLower() == path.ToLower())
                return true;

            if (Environment.GetFolderPath(Environment.SpecialFolder.SendTo).ToLower() == path.ToLower())
                return true;

            if (Environment.GetFolderPath(Environment.SpecialFolder.CDBurning).ToLower() == path.ToLower())
                return true;

            if (Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData).ToLower() == path.ToLower())
                return true;

            if (Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData).ToLower() == path.ToLower())
                return true;

            if (path.ToLower().Contains("$recycle"))
                return true;

            return false;
        }
    }
}
